package com.cea.papyrus.core.commands.copypaste;

import java.util.Iterator;

import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gef.commands.Command;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;

/** 
 * Command that pastes elements in the clipboard to a parent element.
 * This class works as a wrapper for an EMF paste command.
 */
public class PasteFromClipboardCommand extends Command {

	/** the wrapped emf command */
	protected org.eclipse.emf.common.command.Command emfPasteCommand;
	
	/**
	 * Constructs a Command with the specified label.
	 * @param umlElement uml element to paste
	 * @param domain editing domain linked to the element that will own elements pasted from the clipboard
	 */
	public PasteFromClipboardCommand (Element umlElement, EditingDomain domain) {
		setLabel("paste");
		emfPasteCommand= org.eclipse.emf.edit.command.PasteFromClipboardCommand.create(domain, umlElement, null);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#canExecute()
	 */
	@Override
	public boolean canExecute() {
		return emfPasteCommand.canExecute();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#canUndo()
	 */
	@Override
	public boolean canUndo() {
		return emfPasteCommand.canUndo();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#dispose()
	 */
	@Override
	public void dispose() {
		emfPasteCommand.dispose();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#execute()
	 */
	@Override
	public void execute() {
		emfPasteCommand.execute();
		Iterator it = emfPasteCommand.getResult().iterator();
		while(it.hasNext()) {
			Object o = it.next();
			if(o instanceof NamedElement) {
				computeNewName((NamedElement)o);
			}
		}
	}

	/**
	 * Computes new name for the newly created element
	 * @param element
	 */
	protected void computeNewName(NamedElement element) {
		// basic name: simply adds copy_of_ in front of the name of the duplicated element
		String initialName = "copy_of_"+element.getName();
		
		// the new name of the element
		String name = initialName;

		// if name already exists, try to find a new one
		if(isNameReserved(element, name)) {
			name = findNewNameWithSuffix(element, name);
		} 
		element.setName(name);
	}
	
	/**
	 * This methods try to find a new name, using a suffix "_"+number
	 * @param element the element to be named
	 * @param rootName the prefix of the name that will be used
	 * @return a name that does not already exists for this element
	 */
	protected String findNewNameWithSuffix(Element element, String rootName) {
		String name = "";
		for(int i=0; i< 10001 ; i++ ) {
			name = rootName+"_"+i;
			if(!isNameReserved(element, name)) {
				return name;
			}
		}
		return rootName;
	}
	
	/**
	 * return <code>true</code> if the name already exists for the specified element.
	 * @param element the element that will be renamed
	 * @param name the target name
	 * @return <code>true</code> if the name already exists
	 */
	protected boolean isNameReserved(Element element, String name) {
		// iterate in the siblings set of elements
		Iterator it = element.getOwner().getOwnedElements().iterator();
		while(it.hasNext()) {
			Object o = it.next();
			
			// does name already exists ?
			if(o instanceof NamedElement) {
				if(name.equals(((NamedElement)o).getName())) {
					return true;
				}
			}
		}
		return false;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#redo()
	 */
	@Override
	public void redo() {
		emfPasteCommand.redo();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.commands.Command#undo()
	 */
	@Override
	public void undo() {
		emfPasteCommand.undo();
	}

}
